<?php

namespace App\Helpers\Response;

use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Response as HttpResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Arr;

/**
 * 接口返回对象Response
 */
class ResponseTrait
{
    /**
     * 失败返回对象
     *
     * @param string $message
     * @param integer $code
     * @param [type] $data
     * @param array $header
     * @param integer $options
     * @return void
     */
    public function fail(string $message = '', int $code = HttpResponse::HTTP_INTERNAL_SERVER_ERROR, $data = null, array $header = [], int $options = 0)
    {
        $this->response(
            $this->formatData(null, $message, $code),
            $code,
            $header,
            $options
        )->throwResponse();
    }

    /**
     * 成功返回对象
     *
     * @param  JsonResource|array|null  $data
     * @param  string  $message
     * @param  int  $code
     * @param  array  $headers
     * @param  int  $option
     *
     * @return JsonResponse|JsonResource
     * @throws InvalidEnumValueException
     */
    public function success($data = null, string $message = '', $code = HttpResponse::HTTP_OK, array $headers = [], $option = 0)
    {
        if (isset($data['meta']['pagination'])) {
            return $this->formatPaginatedArrayResponse(...func_get_args());
        }
        if ($data instanceof JsonResource) {
            $this->formatResourceResponse(...func_get_args());
        }

        if ($data instanceof LengthAwarePaginator) {
            return $this->formatPaginatedResourceResponse(...func_get_args());
        }
        return $this->formatArrayResponse($data, $message, $code, $headers, $option);
    }

    /**
     * 格式化数组数据
     *
     * @param  array|null  $data
     * @param  string  $message
     * @param  int  $code
     * @param  array  $headers
     * @param  int  $option
     *
     * @return JsonResponse
     */
    protected function formatArrayResponse($data, string $message = '', $code = HttpResponse::HTTP_OK, array $headers = [], $option = 0)
    {
        return $this->response($this->formatData($data, $message, $code), $code, $headers, $option);
    }

    /**
     * 返回API的数组结构
     * @param  JsonResource|array|null  $data
     * @param $message
     * @param $code
     * @return array
     */
    protected function formatData($data, $message, &$code)
    {
        // if (isset($data['data'])) {
        //     if (isset($data['pagination'])) {
        //         $tempData = $data;
        //     } else {
        //         $tempData = $data['data'];
        //     }
        // }
        $result = [
            'code' => $code,
            'data' => $data ?? [],
        ];
        // if (!empty($data) && is_array($data)) {
        //     $result['data'] = $data['data'];

        //     if (!empty($data['pagination'])) {
        //         $result['pagination'] = $data['pagination'];
        //     }
        // }

        if (!empty($message)) {
            array_push($result, ['message' => $message]);
        }

        return $result;
    }

    /**
     * 格式化分页数据(对象)
     *
     * @param  $resource
     * @param  string  $message
     * @param  int  $code
     * @param  array  $headers
     * @param  int  $option
     *
     * @return HigherOrderTapProxy|mixed
     * @throws InvalidEnumValueException
     */
    protected function formatPaginatedResourceResponse($resource, string $message = '', $code = HttpResponse::HTTP_OK, array $headers = [], $option = 0)
    {
        $paginated = $resource->toArray();

        $paginationInformation = [
            'total' => $paginated['total'] ?? null,
            'per_page' => $paginated['per_page'] ?? null,
            'current_page' => $paginated['current_page'] ?? null,
        ];

        $data = array_merge_recursive(['data' => $paginated['data']], $paginationInformation);

        return $this->response($this->formatData($data, $message, $code), $code, $headers, $option);
    }

    /**
     * 格式化分页数据(数组)
     *
     * @param [array] $data
     * @param string $message
     * @param [type] $code
     * @param array $headers
     * @param integer $option
     * @return void
     */
    protected function formatPaginatedArrayResponse($data, string $message = '', $code = HttpResponse::HTTP_OK, array $headers = [], $option = 0)
    {
        $paginated = $data['meta']['pagination'];

        $paginationInformation = [
            'pagination' => [
                'total' => $paginated['total'] ?? 0,
                'per_page' => $paginated['per_page'] ?? null,
                'current_page' => $paginated['current_page'] ?? 1,
                'total_pages' => $paginated['total_pages'] ?? 1,
            ],
        ];

        $data = array_merge_recursive(['data' => $data['data']], $paginationInformation);
        return $this->response($this->formatData($data, $message, $code), $code, $headers, $option);
    }

    /**
     * 格式化JsonResource数据
     *
     * @param  JsonResource  $resource
     * @param  string  $message
     * @param  int  $code
     * @param  array  $headers
     * @param  int  $option
     *
     * @return HigherOrderTapProxy|mixed
     */
    protected function formatResourceResponse($resource, string $message = '', $code = HttpResponse::HTTP_OK, array $headers = [], $option = 0)
    {
        return tap(
            $this->response($this->formatData($this->parseDataFrom($resource), $message, $code), $code, $headers, $option),
            function ($response) use ($resource) {
                $response->original = $resource->resource;
                $resource->withResponse(request(), $response);
            }
        );
    }

    /**
     * JsonResource解析数据
     *
     * @param  JsonResource  $data
     * @return array
     */
    protected function parseDataFrom(JsonResource $data)
    {
        return array_merge_recursive($data->resolve(request()), $data->with(request()), $data->additional);
    }

    /**
     * 返回json数据
     *
     * @param  mixed  $data
     * @param  array  $headers
     * @param  int  $options
     * @return \Illuminate\Http\JsonResponse
     */
    protected function response($data = [], $status = HttpResponse::HTTP_OK, array $headers = [], $options = 0)
    {

        return response()->json($data, $status, $headers, $options);
    }
}
